<?php
/*
Version 0.1
SEMF - Web Desiging Framework for Sport Event Managment
Copyright (C) 2006, SEMF Developers

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/
include_once("token.php");
include_once("statement.php");

class script_parser
{
	private $tokens;
	private $tokens_len;
	private $semf_root;
	private $current_token;
	private $statement_dir;
	private $statement_classes;
	
	private $error_msg;
	
	private $line_no;
	private $col_no;
	
	private $description;
	
	public function __construct($tokens, $semf_root, $description)
	{
		$this->tokens = $tokens;
		$this->tokens_len = count($tokens);
		$this->semf_root = $semf_root;
		$this->error_msg = "";
		
		$this->statement_dir = $semf_root."page_designer/script/statement/";
		$this->current_index = 0;
		
		$this->line_no = 0;
		$this->col_no = 0;
		
		$this-> description = $description;
		
		//$this->load_statements();
		//print_r($statement_classes);
		//print_r($tokens);
	}
	
	public function parse()
	{
		$start = 0;
		$end = $this->tokens_len;
		
		//echo $end."\n";
		
		$root = new statement(statement::$ROOT, $start, $end);
		
		$this->parse_statement($start, $end, $root, 1);
		
		//$root->print_this();
		return $root;
	}
	
	
	public function get_errors()
	{
		return $this->error_msg;
	}
	
	public function report_error($error_msg)
	{
		if( $this->error_msg == "" ) // the first one
		{
			$this->error_msg .= $this->description;
			echo $this->description;
		}
		$error_msg = "PARSE_ERROR:\n".
						$error_msg."\n<hr/>";
		$this->error_msg .= $error_msg;
		echo $error_msg;
	}
	
	public function get_token($i, $end)
	{
		//echo $end."\n";
		if($i <= $end)
		{
			$token = $this->tokens[$i];
			
			$this->line_no = $token->line_no;
			$this->col_no = $token->col_no;
			// echo $token->value.",".$this->line_no.",".$this->col_no."\n";
			return $token->type;
		}
		return NULL;
	}
	
	// to parse statements
	public function parse_statement($start, $end, $parent, $no)
	{
		$i = $this->parse_if_statement($start, $end, $parent, $no);
		if($i != -1 && $i >= $start) //it is an if statement.
		{
			//echo "if found";
			$start = $i+1;
			return $this->parse_statement($start, $end, $parent, $no+1);
		}
		$i = $this->parse_select_statement($start, $end, $parent, $no);
		if($i != -1 && $i >= $start) //it is an select statement.
		{
			//echo "select found";
			$start = $i+1;
			return $this->parse_statement($start, $end, $parent, $no+1);
		}
		$i = $this->parse_decl_statement($start, $end, $parent, $no);
		if($i != -1 && $i >= $start) //it is an declare statement.
		{
			//echo "declare found";
			$start = $i+1;
			return $this->parse_statement($start, $end, $parent, $no+1);
		}
		$i = $this->parse_delete_statement($start, $end, $parent, $no);
		if($i != -1 && $i >= $start) //it is an delete statement.
		{
			//echo "delete found";
			$start = $i+1;
			return $this->parse_statement($start, $end, $parent, $no+1);
		}
		
		$i = $this->parse_expression($start, $end, $parent, $no);
		if($i != -1 && $i >= $start) //it is an expression.
		{
			//echo "it is here,".$i."\n";
			//echo "expression found";
			$start = $i+1;
			return $this->parse_statement($start, $end, $parent, $no+1);
		}
	}
	
	// to parse expression
	public function parse_expression($start, $end, $parent, $no)
	{
		
		
		$i = $start;
		$temp_token = $this->get_token($i, $end);
		
		//yet to be implemented..
		if($temp_token == token::$NOT_EXPR ||
				$temp_token == token::$ADD_ADD ||
				$temp_token == token::$SUB_SUB)
		{
			$this->report_error("!, ++, -- symbols are not yet indetified by SEMF");
			return -1;
		}
		
		//first check for a function..
		
		// trying to get some middle operator at first;
		{
			//now the brackets have gone..
			$new_end = -1;
			$i = $start;
			while(true)
			{
				if ($i > $end)
				{
					break;
				}
				//first brackets have to be bypassed..
				$token = $this->get_token($i++, $end);
				if ($token == token::$OPEN_BRACKET)
				{
					$count = 1;
					while ($count != 0)
					{
						$token = $this->get_token($i++, $end);
						if($token == NULL)
						{
							$this->report_error("Expression block is not closed propertly");
							return -1;
							
						}
						if($token == token::$OPEN_BRACKET)
						{
							$count ++;
						}
						elseif($token == token::$CLOSE_BRACKET)
						{
							$count --;
						}
					}
				}
				if ($i > $end)
				{
					break;
				}
				//first just few higher precedence ones
				if($token == token::$SEMI_COL)
				{
					//echo "alert\n";
					$stat = new statement(statement::$STATEMENT, $start, $i-2); //excluding the ';'
					$parent->add_child("expr".$no, $stat);
					//echo "before new_end is ".($i-2)."\n";
					$new_end = $this->parse_statement($start, $i-2, $stat, 1);
					//echo "after new_end is ".$new_end."\n";
					$new_end = $i-1; //because $i is already incremented one..
					break;
				}
				elseif($token == token::$OR)
				{
					$new_end = 
					  $this->two_side_expression(statement::$OR, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$AND)
				{
					$new_end = 
					  $this->two_side_expression(statement::$AND, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
			}
			if( $new_end != -1)
			{
				return $new_end;
			}
			//again the brackets have gone..
			$new_end = -1;
			$i = $start;
			while(true)
			{
				if ($i > $end)
				{
					break;
				}
				//first brackets have to be bypassed..
				$token = $this->get_token($i++, $end);
				if ($token == token::$OPEN_BRACKET)
				{
					$count = 1;
					while ($count != 0)
					{
						$token = $this->get_token($i++, $end);
						if($token == NULL)
						{
							$this->report_error("Expression block is not closed propertly");
							return -1;
							
						}
						if($token == token::$OPEN_BRACKET)
						{
							$count ++;
						}
						elseif($token == token::$CLOSE_BRACKET)
						{
							$count --;
						}
					}
				}
				if ($i > $end)
				{
					break;
				}
				//first just few higher precedence ones		
				if($token == token::$EQUAL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$EQUAL, $parent, $start, $end, $i-2, $i, $no);
					 
					//echo "when start: $start, end $end, i $i \n";
					//print_r($parent->childs["expr".$no]);
					break;
				}
				elseif($token == token::$EQUILITY)
				{
					$new_end = 
					  $this->two_side_expression(statement::$EQUILITY, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$NOT_EQUILITY)
				{
					$new_end = 
					  $this->two_side_expression(statement::$NOT_EQUILITY, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$LESS_THAN)
				{
					$new_end = 
					  $this->two_side_expression(statement::$LESS_THAN, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$GREATER_THAN)
				{
					$new_end = 
					  $this->two_side_expression(statement::$GREATER_THAN, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$LESS_THAN_EQUAL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$LESS_THAN_EQUAL, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$GREATER_THAN_EQUAL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$GREATER_THAN_EQUAL, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$ADD)
				{
					$new_end = 
					  $this->two_side_expression(statement::$ADD, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$SUB)
				{
					$new_end = 
					  $this->two_side_expression(statement::$SUB, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$MUL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$MUL, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$DIV)
				{
					$new_end = 
					  $this->two_side_expression(statement::$DIV, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$ADD_EQUAL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$ADD_EQUAL, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$SUB_EQUAL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$SUB_EQUAL, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$MUL_EQUAL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$MUL_EQUAL, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
				elseif($token == token::$DIV_EQUAL)
				{
					$new_end = 
					  $this->two_side_expression(statement::$DIV_EQUAL, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
			}
			if($new_end != -1)
			{
				return $new_end;
			}
			// this is really bad, but we have to do this anyway..:(
			$new_end = -1;
			$i = $start;
			while(true)
			{
				if ($i > $end)
				{
					break;
				}
				//first brackets have to be bypassed..
				$token = $this->get_token($i++, $end);
				if ($token == token::$OPEN_BRACKET)
				{
					$count = 1;
					while ($count != 0)
					{
						$token = $this->get_token($i++, $end);
						if($token == NULL)
						{
							$this->report_error("Expression block is not closed propertly");
							return -1;
							
						}
						if($token == token::$OPEN_BRACKET)
						{
							$count ++;
						}
						elseif($token == token::$CLOSE_BRACKET)
						{
							$count --;
						}
					}
				}
				if ($i > $end)
				{
					break;
				}
				//first just few the lowest precedence ones
				if($token == token::$DOT)
				{
					$new_end = 
					  $this->two_side_expression(statement::$DOT, $parent, $start, $end, $i-2, $i, $no);
					break;
				}
			}
			if( $new_end != -1)
			{
				return $new_end;
			}
		}
		

		//check before for function..
		$new_end = $this->parse_function_expression($start, $end, $parent, $no);
		if($new_end != -1)
		{
			return $new_end;
		}
		// so this must be a variable then

		$i = $start;
		$temp_token = $this->get_token($i, $end);
		
		if ($temp_token == token::$CONSTANT || 
			$temp_token == token::$NUMBER ||
			$temp_token == token::$VARIABLE ||
			$temp_token == token::$DATA_VAR ||
			$temp_token == token::$SYS_VAR)
		{
			$statement_type = NULL;
			switch ($temp_token)
			{
				case token::$CONSTANT:
					$statement_type = statement::$CONSTANT;
					break;
				case token::$NUMBER:
					$statement_type = statement::$NUMBER;
					break;
				case token::$VARIABLE:
					$statement_type = statement::$VARIABLE;
					break;
				case token::$DATA_VAR:
					$statement_type = statement::$DATA_VAR;
					break;
				case token::$SYS_VAR:
					$statement_type = statement::$SYS_VAR;
					break;
			}
			$expression = new statement($statement_type, $i, $i);
			$parent ->add_child("expr".$no, $expression);
			
			$token = new statement(statement::$TOKEN, $i, $i);
			$expression ->add_child("expr1", $token);
			
			return $i;
		}
		elseif ($temp_token == token::$NULL)
		{
			$statement_type = statement::$NULL;
			$expression = new statement($statement_type, $i, $i);
			$parent ->add_child("expr".$no, $expression);
			
			return $i;
		}
		elseif ($temp_token == token::$OPEN_BRACKET)
		{
			$count = 1;
			$block_start = $i+1;
			$i++;
			while ($count != 0)
			{
				$token = $this->get_token($i++, $end);
				if($token == NULL)
				{
					$this->report_error("Outer expression block is not closed properly");
					return -1;
				}
				if($token == token::$OPEN_BRACKET)
				{
					$count ++;
				}
				elseif($token == token::$CLOSE_BRACKET)
				{
					$count --;
				}
			}
			//echo "\nblocked finished\n";
			
			$block_end = $i-2; //close bracket is not included..
			
			$expression = new statement(statement::$EXPR, $block_start, $block_end);
			$parent ->add_child("expr".$no, $expression);
			$this->parse_expression($block_start, $block_end, $expression, 1);
			// the end will be ignored..
			
			return $i -1;
			
		}
		return -1;
	}
	
	// two side expression
	// here $i is the end of the first expression,
	// $j is the start of second expression
	private function two_side_expression($statement, $parent, $start, $end, $i, $j, $no)
	{
		
		$new_start = $start;
		$new_end = $i; //excluding the equal //or whatever the symbol
		$expr1 = new statement(statement::$EXPR, $new_start, $new_end);
		$this->parse_expression($new_start, $new_end, $expr1, 1);
		
		$new_start = $j;
		$new_end = $end; //excluding the equal
		$expr2 = new statement(statement::$EXPR, $new_start, $new_end);
		$new_end = $this->parse_expression($new_start, $new_end, $expr2, 1);
		
		$expr_main = new statement($statement, $start, $end);
		$expr_main->add_child("expr1", $expr1);
		$expr_main->add_child("expr2", $expr2);
		
		$parent ->add_child("expr".$no, $expr_main);
		
		return $new_end;
	}

	// to parse if statement
	private function parse_if_statement($start, $end, $parent, $no)
	{
		$i = $start;
		
		//check for the if statement..
				
		if ($this->get_token($i++, $end) == token::$IF)
		{
			$if_expr = new statement(statement::$IF, $start, $end);
			$else_hit = false;
			
			$block_no = 0;
			$block_start = 0;
			$block_end = 0;
			
			$statement_start = 0;
			$statement_end = 0;
			
			while(true)
			{
				$block_no ++; //start a new block
				if($else_hit == false) //only else doesnt have brackets ()
				{
					//echo "\nifs found\n";
					if ($this->get_token($i++, $end) != token::$OPEN_BRACKET)
					{
						if($block_no == 1)
						{
							$this->report_error(
							    "'if' statement should be followed by an open bracket");
						}
						else
						{
							$this->report_error(
							    "'elseif'/'else if' statement should be followed by an open bracket");
						}
						return -1;
					}
					
					$count = 1;
					//start the block from here..
					$block_start = $i;
					while ($count != 0)
					{
						$token = $this->get_token($i++, $end);
						if($token == NULL)
						{
							$this->report_error("Expression block inside 'if' is not closed");
							return -1;
						}
						if($token == token::$OPEN_BRACKET)
						{
							$count ++;
						}
						elseif($token == token::$CLOSE_BRACKET)
						{
							$count --;
						}
					}
					//echo "\nblocked finished\n";
					
					$block_end = $i-2; //close bracket is not included..
					
				}
				
				//now check for the statement inside it.
				//if blocked open chase on closing block
				//this will chase all the blocked unblocked stament in elseifs..

				if ($this->get_token($i++, $end) != token::$OPEN_BLOCK)
				{
					//single line statement.
					$statement_start = $i -1;
					while(($token = $this->get_token($i++, $end)) != ";" ||
							$token != NULL);
					$statement_end = $i -1;
				}
				else //blocked statement..
				{
					$statement_start = $i-1;
					$count = 1;
					while ($count != 0)
					{
						$token = $this->get_token($i++, $end);
						if($token == NULL)
						{
							$this->report_error("statement block inside 'if' is not closed");
							return -1;
						}
						if($token == token::$OPEN_BLOCK)
						{
							$count ++;
						}
						elseif($token == token::$CLOSE_BLOCK)
						{
							$count --;
						}
					}
					$statement_end = $i -1; //includes the close block
				}
				//echo "\nstatement finished\n";
				
				if ($else_hit == false)
				{
					$expression = new statement(statement::$EXPR, $block_start, $block_end);
					$if_expr->add_child("expr".$block_no, $expression);
					$this->parse_expression($block_start, $block_end, $expression, 1);
				}
				$stat = new statement(statement::$STATEMENT, $statement_start+1, $statement_end -1);
				$if_expr->add_child("stmt".$block_no, $stat);
				$this->parse_statement($statement_start+1, $statement_end-1, $stat, 1);
				
				$temp_token = $this->get_token($i++, $end);
				if ($temp_token == token::$ELSEIF)
				{
					//just continue the loop
				}
				else if ($temp_token == token::$ELSE)
				{
					//just continue the loop but with else_hit TRUE;
					//echo "yea it is else";
					$else_hit = TRUE;
				}
				else
				{
					//just stop the loop.
					break;
				}
			}
			//echo $this->get_token($i, $end);
			$i --;$i --; //mean it should undo the last 2 moves.
			
			$if_expr->set_end($i);
			
			$parent ->add_child("stmt".$no, $if_expr);
			//echo "in here";
			return $i;
		} 
		else
		{
			return -1;
		}
	}
	
	// to parse select statement
	private function parse_select_statement($start, $end, $parent, $no)
	{
		$i = $start;
		
		//check for the select statement..
				
		if ($this->get_token($i++, $end) == token::$SELECT)
		{
			$select_expr = new statement(statement::$SELECT, $start, $end);
	
			
			$block_no = 0;
			$block_start = 0;
			$block_end = 0;
			
			$statement_start = 0;
			$statement_end = 0;
			
			//echo "1: $start, $end, $i \n";
			
			
			if ($this->get_token($i++, $end) == token::$FROM)
			{
				$from_expr = new statement(statement::$FROM, $i, $end);
				//echo "1: $i, $end \n";
				$select_expr->add_child("stmt1", $from_expr);
				$block_no = 1;
				while($this->get_token($i, $end) != token::$WHERE && $this->get_token($i, $end) != NULL )
				{
					$table_expression = new statement(statement::$FROM_DECL, $i, $end);
					$start = $i;
					while($this->get_token($i, $end) != token::$DATA_VAR && $this->get_token($i, $end) != NULL)
					{
						$i ++;
					}
					
					if( $i <= $start)
					{
						$this->report_error(
							    "wrong syntax inside FROM.. table names are missing for data object");
						return -1;
					}
					
					$new_end = $this->parse_expression($start, $i-1, $table_expression, 1);
					//echo "2: $i, $new_end \n";
					$new_end = $this->parse_expression($new_end + 1, $new_end + 1, $table_expression, 2);
					//echo "3: $i, $new_end \n";
					
					$table_expression->end = $new_end;
					$i = $new_end + 1;
					
					$from_expr->add_child("stmt".$block_no, $table_expression);
					$block_no ++;
					
					if($this->get_token($i, $end ) != token::$COMMA)
					{
						break;
					}
				}
				$from_expr-> end = $i-1; //update the end..
				
				if ($this->get_token($i, $end) == token::$WHERE) // this can be NULL as well
				{
					$where_expr = new statement(statement::$WHERE, $i, $end);
					$start = $i +1;
					while($this->get_token($i, $end) != token::$SEMI_COL && $this->get_token($i, $end) != NULL)
					{
						$i ++;
					}
					if( $i <= $start)
					{
						$this->report_error(
							    "wrong syntax inside WHERE.. conditions are missing!");
						return -1;
					}
					
					$new_end = $this->parse_expression($start, $i-1, $where_expr, 1 );
					
					$where_expr->end = $new_end;
					
					//adding the where expression
					$select_expr->add_child("stmt2", $where_expr);
					$select_expr-> end = $new_end;
					
					$parent ->add_child("stmt".$no, $select_expr);
					//print_r($select_expr);
					
					return $new_end +1;
				}
				/*else if( $this->get_token($i, $end) != NULL )
				{
					$this->report_error(
							    "wrong syntax around WHERE in SELECT..");
					return -1;
				} */
				else // now whre statement..
				{
					$select_expr-> end = $i  -1;
					$parent ->add_child("stmt".$no, $select_expr);
					
					return $i-1;
				}
			}
			else
			{
				$this->report_error(
							    "'SELECT should be followed by FROM");
			}
			
		}
		else
		{
			return -1;
		}
	}
	// to parse declare statement
	private function parse_decl_statement($start, $end, $parent, $no)
	{
		$i = $start;
		
		//check for the select statement..
				
		if ($this->get_token($i++, $end) == token::$DECL)
		{
	
			
			$block_no = 0;
			$block_start = 0;
			$block_end = 0;
			
			$statement_start = 0;
			$statement_end = 0;
			
			$lhs_token = -1;
			
			//echo "1: $start, $end, $i \n";
			
			
			if ($this->get_token($i, $end) == token::$DATA_VAR)
			{
				$lhs_token = $i;
			}
			else
			{
				$this->report_error(
							    "Data variable should be placed after DECL");
				return -1;
			}
			$i ++;
			
			if($this->get_token($i, $end) == token::$EQUAL) 
			{
			}
			else
			{
				$this->report_error(
							    "EQUAL is missing after DECL and data variable");
			}
			$i ++;
			
			if($this->get_token($i, $end) == token::$NEW) 
			{
			
				$decl_expr = new statement(statement::$DECL, $start, $end);
				//if it is for new the case it declared in this way..
				$new_end = $this->parse_expression($lhs_token, $lhs_token, $decl_expr, 1 );
				
				$i ++;
				
				$start = $i;
				while($this->get_token($i, $end) != token::$SEMI_COL && $this->get_token($i, $end) != NULL)
				{
					$i ++;
				}
				if( $i <= $start)
				{
					$this->report_error(
							"wrong syntax after NEW (no table is specified)!");
					return -1;
				}
				
				$new_end = $this->parse_expression($start, $i-1, $decl_expr, 2 );
				$decl_expr-> end = $new_end;
				
				$parent ->add_child("stmt".$no, $decl_expr);
				//print_r($decl_expr);
				
				return $new_end +1;
			}
			elseif($this->get_token($i, $end) == token::$OPEN_BRACKET)
			{
				$i ++;
				$bracket_start = $i;
				while($this->get_token($i, $end) != NULL &&
				      $this->get_token($i ++, $end) != token::$CLOSE_BRACKET);
				$bracket_end = $i -2;
				if($bracket_start > $bracket_end)
				{
					$this->report_error(
							    "Missing Cast type in the casting..");
					return -1;
				}
				
				$cast_expr = new statement(statement::$CAST, $start, $end);
				//if it is for new the case it declared in this way..
				$new_end = $this->parse_expression($lhs_token, $lhs_token, $cast_expr, 1);	
				$new_end = $this->parse_expression($bracket_start, $bracket_end, $cast_expr, 2);
				
				if($this->get_token($i, $end) != token::$DATA_VAR)
				{
					$this->report_error(
							    "The CAST is not followed by a data variable..");
					return -1;
				}
				$new_end = $this->parse_expression($i, $i, $cast_expr, 3);
				$cast_expr-> end = $new_end;
				$parent ->add_child("stmt".$no, $cast_expr);
				
				return $new_end + 1;
			}
			else
			{
				//just evaluate whatever in there..
				/*$assigner_expr = new statement(statement::$ASSIGNER, $start, $end);
				//if it is for new the case it declared in this way..
				$new_end = $this->parse_expression($lhs_token, $lhs_token, $assigner_expr, 1);
				
				$new_start = $i;
				$expr = new statement(statement::$EXPR, $new_start, $end);
				$new_end = $this->parse_expression($new_start, $end, $assigner_expr, 2);
				$parent->add_child("stmt".$no, $assigner_expr);
				
				return new_end + 1; */
				
				$this->report_error(
							    "NEW or the CAST Operator is missing at left hand side of DECL");
				return -1;
			}

		}
		else
		{
			return -1;
		}
	}

	// to parse delete statement
	private function parse_delete_statement($start, $end, $parent, $no)
	{
		$i = $start;
		
		//check for the select statement..
		if ($this->get_token($i++, $end) == token::$DELETE)
		{
			$del_stmt = new statement(statement::$DELETE, $start, $end);
	
						
			$start = $i;
			while($this->get_token($i, $end) != token::$SEMI_COL && $this->get_token($i, $end) != NULL)
			{
				$i ++;
			}
			if( $i <= $start)
			{
				$this->report_error(
						"wrong syntax after DELETE (no table is specified)!");
				return -1;
			}
			
			$new_end = $this->parse_expression($start, $i-1, $del_stmt, 1 );
			$del_stmt-> end = $new_end;
			
			$parent ->add_child("stmt".$no, $del_stmt);
			
			return $new_end +1;
		}
		else
		{
			return -1;
		}
	}
	
	//parse function
	private function parse_function_expression($start, $end, $parent, $no)
	{
		$i = $start;
		
		//echo "working on: ".$this->get_token($i, $end)."\n";
		
		//check for the function name..
		$funct_name_token = -1;
		if($this->get_token($i, $end) !=  token::$CONSTANT)
		{
			return -1;
		}
		$funct_name_token = $i;
		$i ++;
		
		$func_stmt = new statement(statement::$FUNCTION, $start, $end);

		$func_name_stmt = new statement(statement::$TOKEN, $funct_name_token, $funct_name_token);
		$func_stmt ->add_child("expr1", $func_name_stmt);
		
		//dump the familar code...
		$token = $this->get_token($i, $end);
		$param_start = $param_end = 0;
		
		
		if ($token == token::$OPEN_BRACKET)
		{
			$count = 1;
			$i ++;
			$param_start = $i;
			while ($count != 0)
			{
				$token = $this->get_token($i++, $end);
				if($token == NULL)
				{
					$this->report_error("Expression block in function is not closed propertly");
					return -1;
					
				}
				if($token == token::$OPEN_BRACKET)
				{
					$count ++;
				}
				elseif($token == token::$CLOSE_BRACKET)
				{
					$count --;
				}
			}
			$param_end = $i -2;
		}
		else
		{
			return -1;
		}
	
		
		$params_stmt = new statement(statement::$PARAMS, $param_start, $param_end);
		if($this->parse_param_statement($param_start, $param_end, $params_stmt) == -1)
		{
			return -1;
		}
		$func_stmt ->add_child("expr2", $params_stmt);
		
		$parent ->add_child("expr".$no, $func_stmt);
		$func_stmt-> end = $i -1;
		//echo $this->tokens[$i]->value."\n";
		return $i-1;
	}
	
	private function parse_param_statement($start, $end, $params_stmt) //we dont need the no here..
	{
		$i = $start;
		$param_count = 0;
		while($i <= $end) //iterate through all parameters..
		{
			$param_count ++;
			$param_start = $i;
			$token = $this->get_token($i ++, $end);
			while($token != NULL &&
					 $token != token::$COMMA)
			{	
				//just to ignore brackets..
				if ($token == token::$OPEN_BRACKET)
				{
					$count = 1;
					while ($count != 0)
					{
						$token = $this->get_token($i++, $end);
						if($token == NULL)
						{
							$this->report_error("Expression block in function is not closed propertly");
							return -1;
							
						}
						if($token == token::$OPEN_BRACKET)
						{
							$count ++;
						}
						elseif($token == token::$CLOSE_BRACKET)
						{
							$count --;
						}
					}
					$i --;
				}
				
				$token = $this->get_token($i ++, $end);
			}
			$param_end = $i -2; // this is ignoring the comma..
			$this->parse_statement($param_start, $param_end, $params_stmt, $param_count);
		}
		return $i;
	}
}
?>